package com.cloudkinto.service.role.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.MenuDao;
import com.cloudkinto.dao.RoleMenuRelationDao;
import com.cloudkinto.dao.UserDao;
import com.cloudkinto.entity.MenuDo;
import com.cloudkinto.entity.RoleDo;
import com.cloudkinto.dao.RoleDao;
import com.cloudkinto.entity.RoleMenuRelationDo;
import com.cloudkinto.entity.UserDo;
import com.cloudkinto.service.finance.RechargeRecordService;
import com.cloudkinto.service.invoice.InvoiceRecordService;
import com.cloudkinto.service.message.MessageNoticeService;
import com.cloudkinto.service.role.RoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.service.role.vo.menu.MenuButtonRes;
import com.cloudkinto.service.role.vo.menu.MenuLoginTreeRes;
import com.cloudkinto.service.role.vo.role.*;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * service实现类
 * </p>
 *
 * @author 张永远
 * @since 2020-05-29
 */
@Service
@Transactional(rollbackFor = Exception.class)//事务回滚
public class RoleServiceImpl extends ServiceImpl<RoleDao, RoleDo> implements RoleService {
    @Autowired
    private RoleDao dao;
    @Autowired
    private RoleMenuRelationDao roleMenuRelationDao;
    @Autowired
    private MenuDao menuDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private RechargeRecordService rechargeRecordService;
    @Autowired
    private InvoiceRecordService invoiceRecordService;
    @Autowired
    private MessageNoticeService messageNoticeService;


    @Override
    public RoleAddReq add(RoleAddReq req, Long userId, Long companyId) {
        addCheck(req, companyId);
        RoleDo entityDo = new RoleDo();
        BeanUtils.copyProperties(req, entityDo);
        handlerAddBefore(entityDo, userId);
        if (companyId == null) {
            companyId = -1L;
        }
        entityDo.setCompanyId(companyId);
        entityDo.setRoleType(companyId == -1L ? 2 : 1);
        dao.insert(entityDo);
        return req;
    }

    @Override
    public void giveMenu(RoleGiveMenuReq req, Long userId) {
        LambdaQueryWrapper<RoleMenuRelationDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleMenuRelationDo::getRoleId, req.getRoleId());
        //查询这个角色 所有的权限
        List<RoleMenuRelationDo> roleMenuRelationDos = roleMenuRelationDao.selectList(wrapper);
        Set<Long> menuIds = new HashSet<>(roleMenuRelationDos.stream().map(RoleMenuRelationDo::getMenuId).collect(Collectors.toList()));
        for (RoleMenuRelationDo roleMenuRelationDo : roleMenuRelationDos) {
            MenuDo menuDo = menuDao.selectById(roleMenuRelationDo.getMenuId());
            if (menuDo == null || (menuDo.getSystem() == 0 && !req.getMenuIds().contains(menuDo.getId()))) {
                roleMenuRelationDao.deleteById(roleMenuRelationDo.getId());
            }
        }

        for (Long menuId : req.getMenuIds()) {
            //判断需不需要插入
            if (menuIds.contains(menuId)) {
                continue;
            }
            RoleMenuRelationDo relationDo = new RoleMenuRelationDo();
            relationDo.setRoleId(req.getRoleId());
            relationDo.setMenuId(menuId);
            roleMenuRelationDao.insert(relationDo);
        }
    }

    @Override
    public SingleResult giveMenuInit(Long id) {
        LambdaQueryWrapper<RoleMenuRelationDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleMenuRelationDo::getRoleId, id);
        List<RoleMenuRelationDo> relationDoList = roleMenuRelationDao.selectList(wrapper);
        Set<Long> menuSet = new HashSet<>();
        for (RoleMenuRelationDo relationDo : relationDoList) {
            menuSet.add(relationDo.getMenuId());
        }


        List<RoleGiveMenuInitTree> treeList = new ArrayList<>();

        LambdaQueryWrapper<MenuDo> menuWrapper = new LambdaQueryWrapper<>();
        menuWrapper.eq(MenuDo::getParentId, 0L).eq(MenuDo::getSystem, 0).orderByAsc(MenuDo::getSort);
        List<MenuDo> menuDoList = menuDao.selectList(menuWrapper);
        if (!CollectionUtils.isEmpty(menuDoList)) {
            for (MenuDo menuDo : menuDoList) {
                RoleGiveMenuInitTree tree = new RoleGiveMenuInitTree();
                tree.setId(menuDo.getId());
                tree.setName(menuDo.getName());
                tree.setUrl(menuDo.getUrl());
                tree.setIcon(menuDo.getIcon());
                tree.setComponent(menuDo.getComponent());
                tree.setType(1);//父菜单
                List<RoleGiveMenuInitTree> children = queryChildren(menuDo.getId(), menuSet, 2);
                if (children.size() == 0) {
                    //在筛选按钮
                    children = this.queryButton(menuDo.getId(), menuSet);
                    tree.setType(1); //说明 一级菜单
                }
                else {
                    tree.setType(2);//说明 二级菜单
                }
                tree.setChildren(children);
                tree.setStatus(checkStatus(menuDo.getId(), menuSet) ? 1 : 0);
                treeList.add(tree);
            }
        }
        return SingleResult.success(treeList);
    }

    private List<RoleGiveMenuInitTree> queryChildren(Long menuId, Set<Long> menuSet, int type) {
        if (menuId != null) {
            LambdaQueryWrapper<MenuDo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(MenuDo::getParentId, menuId).eq(MenuDo::getSystem, 0).eq(MenuDo::getType, type).orderByAsc(MenuDo::getSort);
            List<MenuDo> menuDoList = menuDao.selectList(wrapper);
            List<RoleGiveMenuInitTree> treeList = new ArrayList<>();

            for (MenuDo menuDo : menuDoList) {
                RoleGiveMenuInitTree tree = new RoleGiveMenuInitTree();
                tree.setId(menuDo.getId());
                tree.setName(menuDo.getName());
                List<RoleGiveMenuInitTree> children = queryChildren(menuDo.getId(), menuSet, type);
                if (children.size() == 0) {
                    //在筛选按钮
                    children = this.queryButton(menuDo.getId(), menuSet);
                }
                tree.setChildren(children);
                tree.setType(2);
                tree.setStatus(checkStatus(menuDo.getId(), menuSet) ? 1 : 0);
                treeList.add(tree);
            }
            return treeList;

        }
        return null;
    }

    private boolean checkStatus(Long menuId, Set<Long> menuSet) {
        if (menuId != null && menuSet.contains(menuId)) {
            return true;
        }
        return false;
    }

    //新增校验
    private void addCheck(RoleAddReq req, Long companyId) {
        LambdaQueryWrapper<RoleDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleDo::getRoleName, req.getRoleName()).eq(RoleDo::getCompanyId, companyId);
        int count = this.baseMapper.selectCount(wrapper);
        if (count > 0) {
            throw new BizException(SysConstant.Role_AddCheck_Name);
        }
    }

    //做新增之前要执行的业务定制处理
    private void handlerAddBefore(RoleDo entityDo, Long userId) {
        entityDo.setCreateBy(userId);
        entityDo.setCreateTime(new Date());
        entityDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
    }

    //将新增的do转换成要返回的实体
    private Object handlerAddAfter(RoleDo entityDo) {
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return res;
    }

    @Override
    public SingleResult updateInit(Long id) {
        RoleDetailRes res = new RoleDetailRes();
        RoleDo roleDo = this.baseMapper.selectById(id);
        res.setId(roleDo.getId());
        res.setRoleName(roleDo.getRoleName());
        res.setRoleType(roleDo.getRoleType());
        return SingleResult.success(res);
    }

    @Override
    public RoleUpdateReq update(RoleUpdateReq req, Long userId) {
        RoleDo entityDo = dao.selectById(req.getId());
        if (entityDo == null) {
            throw new BizException(SysConstant.Role_Update_Notfound);
        }
        updateCheck(req, entityDo.getCompanyId());
        BeanUtils.copyProperties(req, entityDo);
        handlerUpdateBefore(entityDo, userId);
        dao.updateById(entityDo);
        return req;
    }

    //编辑校验
    private void updateCheck(RoleUpdateReq req, Long companyId) {
        LambdaQueryWrapper<RoleDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleDo::getRoleName, req.getRoleName()).ne(RoleDo::getId, req.getId()).eq(RoleDo::getCompanyId, companyId);
        int count = this.baseMapper.selectCount(wrapper);
        if (count > 0) {
            throw new BizException(SysConstant.Role_AddCheck_Name);
        }
    }

    //做修改之前要执行的业务定制处理
    private void handlerUpdateBefore(RoleDo entityDo, Long userId) {
        entityDo.setUpdateBy(userId);
        entityDo.setUpdateTime(new Date());
    }

    @Override
    public int delete(Long id, Long userId) {
        RoleDo entityDo = dao.selectById(id);
        deleteCheck(entityDo);
        handlerDeleteBefore(entityDo, userId);
        return dao.deleteById(id);
    }

    private void deleteCheck(RoleDo entityDo) {
        if (StringUtils.isNotBlank(entityDo.getDevCode())) {
            throw new BizException(SysConstant.Role_Delete_Error);
        }

        LambdaQueryWrapper<RoleMenuRelationDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleMenuRelationDo::getRoleId, entityDo.getId());
        int count = roleMenuRelationDao.selectCount(wrapper);
        if (count > 0) {
            throw new BizException(SysConstant.Role_Delete_HadChild);
        }

        LambdaQueryWrapper<UserDo> userDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userDoLambdaQueryWrapper.eq(UserDo::getRoleId, entityDo.getId());
        int userCount = userDao.selectCount(userDoLambdaQueryWrapper);
        if (userCount > 0) {
            throw new BizException(SysConstant.Role_Delete_HadUser);
        }
    }

    //做删除之前要执行的业务定制处理
    private void handlerDeleteBefore(RoleDo entityDo, Long userId) {
        entityDo.setDeleteBy(userId);
        entityDo.setDeleteTime(new Date());
        this.baseMapper.updateById(entityDo);
    }

    @Override
    public Object detail(Long id) {
        RoleDo entityDo = dao.selectById(id);
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return handlerDetailAfter(res);
    }

    //查询明细之后要执行的业务定制处理
    private Object handlerDetailAfter(Object res) {
        return res;
    }


    @Override
    public PageResult getListPage(Map<String, String> map) {
        QueryWrapper<RoleDo> wrapper = queryBuild(map);
        IPage<RoleDo> page = pageInit(map);
        page = this.page(page, wrapper);
        List<RolePageRes> resList = handlerListAfter(page.getRecords());
        PageResult result = new PageResult(resList, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        return result;
    }

    @Override
    public List<MenuLoginTreeRes> getMenuTree(Long roleId, Integer language, Long companyId) {
        List<MenuLoginTreeRes> treeResList = new ArrayList<>();

        LambdaQueryWrapper<RoleMenuRelationDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleMenuRelationDo::getRoleId, roleId);
        List<RoleMenuRelationDo> relationDoList = roleMenuRelationDao.selectList(wrapper);
        Set<Long> menuIdSet = relationDoList.stream().map(RoleMenuRelationDo::getMenuId).collect(Collectors.toSet());

        LambdaQueryWrapper<MenuDo> menuWrapper = new LambdaQueryWrapper<>();
        menuWrapper.eq(MenuDo::getParentId, 0L).eq(MenuDo::getSystem, 0).orderByAsc(MenuDo::getSort);
        List<MenuDo> menuDoList = menuDao.selectList(menuWrapper);
        if (!CollectionUtils.isEmpty(menuDoList)) {
            menuDoList.forEach(menuDo -> {
                if (!menuIdSet.contains(menuDo.getId())) {
                    return;
                }
                MenuLoginTreeRes res = new MenuLoginTreeRes();
                res.setIcon(menuDo.getIcon());
                res.setId(menuDo.getId());
                res.setName(language == 1 ? menuDo.getName() : menuDo.getJpName());
                res.setUrl(menuDo.getUrl());
                res.setComponent(menuDo.getComponent());
                res.setType(0);
                res.setChildren(queryFindChildren(menuDo.getId(), menuIdSet, language, 2));//筛选菜单
//                if (menuDo.getId() == 283) {
//                    //仓库配置 异常库位未处理数
//                    res.setCount(messageNoticeService.getRackUnDealCount());
//                }
                treeResList.add(res);
            });
        }

        return treeResList;
    }


    private List<RoleGiveMenuInitTree> queryFindChildren(Long menuId, Set<Long> menuIdSet, Integer language, Integer type) {
        if (menuId != null) {
            LambdaQueryWrapper<MenuDo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(MenuDo::getParentId, menuId).eq(MenuDo::getSystem, 0).eq(MenuDo::getType, type).orderByAsc(MenuDo::getSort);
            List<MenuDo> menuDoList = menuDao.selectList(wrapper);
            List<RoleGiveMenuInitTree> treeList = new ArrayList<>();
            menuDoList.forEach(menuDo -> {
                if (!menuIdSet.contains(menuDo.getId())) {
                    return;
                }
                RoleGiveMenuInitTree res = new RoleGiveMenuInitTree();
                res.setUrl(menuDo.getUrl());
                res.setComponent(menuDo.getComponent());
                res.setName(language == 1 ? menuDo.getName() : menuDo.getJpName());
                res.setId(menuDo.getId());
                res.setIcon(menuDo.getIcon());
                res.setType(2);
                List<RoleGiveMenuInitTree> children = queryFindChildren(menuDo.getId(), menuIdSet, language, type);
                if (children.size() == 0) {
                    //在筛选按钮
//                    children = this.queryButton(menuDo.getId(), menuIdSet);
                }
                res.setChildren(children);
//                if (menuDo.getId() == 445) {
//                    //异常库位 异常库位未处理数
//                    res.setCount(messageNoticeService.getRackUnDealCount());
//                }
                treeList.add(res);
            });
            return treeList;

        }
        return null;
    }

    public List<RoleGiveMenuInitTree> queryButton(Long menuId, Set<Long> menuSet) {
        //在筛选按钮
        LambdaQueryWrapper<MenuDo> buttonWra = new LambdaQueryWrapper<>();
        buttonWra.eq(MenuDo::getParentId, menuId).eq(MenuDo::getSystem, 0).eq(MenuDo::getType, 3).in(MenuDo::getShowFor, 0, 1).orderByAsc(MenuDo::getSort);
        List<MenuDo> button = menuDao.selectList(buttonWra);

        List<RoleGiveMenuInitTree> buttonList = new ArrayList<>();
        for (MenuDo b : button) {
            RoleGiveMenuInitTree buttonRes = new RoleGiveMenuInitTree();
            BeanUtils.copyProperties(b, buttonRes);
            buttonRes.setStatus(this.checkStatus(b.getId(), menuSet) ? 1 : 0);
            buttonRes.setType(3);
            buttonList.add(buttonRes);
        }
        return buttonList;
    }


    //查询分页列表之后对列表数据的处理
    private List<RolePageRes> handlerListAfter(List<RoleDo> list) {
        List<RolePageRes> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            for (RoleDo roleDo : list) {
                RolePageRes res = new RolePageRes();
                res.setId(roleDo.getId());
                res.setRoleName(roleDo.getRoleName());
                res.setDevCode(roleDo.getDevCode());
                try {
                    res.setRoleTypeName(roleDo.getRoleType() == 1 ? "客户角色" : "后台角色");
                } catch (Exception e) {

                }
                result.add(res);
            }
        }
        return result;
    }

    private IPage<RoleDo> pageInit(Map<String, String> map) {
        IPage<RoleDo> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }

    private QueryWrapper<RoleDo> queryBuild(Map<String, String> map) {
        QueryWrapper<RoleDo> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(map.get("keyword"))) {
            wrapper.like("role_name", map.get("keyword"));
        }
        if (StringUtils.isNotBlank(map.get("userId"))) {
            UserDo userDo = userDao.selectById(map.get("userId"));
            if (userDo != null && userDo.getCompanyId() != null) {
                map.put("companyId", userDo.getCompanyId() +"");
            }
        }
        if (StringUtils.isNotBlank(map.get("companyId"))) {
            wrapper.eq("company_id", map.get("companyId"));
        }
        else {
            wrapper.eq("company_id", -1L);

        }

        wrapper.orderByDesc("id");
        return wrapper;
    }


}
